#include <stdlib.h>
#include <stdio.h>
//#include <unistd.h>
#include <nds.h>
//#include <fat.h>
#include <dirent.h>

// common headers
#include "common.h"

// local headers

#include "filelist.h"

LLIST *getFileList(char *selectpath) {
	DIR *pdir;
	struct dirent *pent;
	struct stat st;
	LLIST *dirs=NULL, *files=NULL, *tmp=NULL, *prevf=NULL, *prevd=NULL, *selectd=NULL;

	pdir=std->opendir(".");
	if(!pdir) return NULL;

	while((pent=std->readdir(pdir))) {
		if(!std->strcmp(".", pent->d_name)) continue;

		tmp=NULL;
		if(std->stat(pent->d_name, &st)) continue;
		if(S_ISREG(st.st_mode)) {	// regular file
            tmp=prevf=ll->append_el(&prevf, x->xmalloc(sizeof(sFileT)));
            if(!files) files=tmp;
		}
		else {
            tmp=prevd=ll->append_el(&prevd, x->xmalloc(sizeof(sFileT)));
			if(!dirs) dirs=tmp;
		}

		std->strncpy(SF(tmp)->name, pent->d_name, 256);
		SF(tmp)->type=!!S_ISREG(st.st_mode);
	}
	std->closedir(pdir);

	ll->sort(dirs, (datacmp)cmpSF);
	ll->sort(files, (datacmp)cmpSF);

	if(selectpath) {
		tmp=dirs;
		while(tmp) {
			if(!std->strcasecmp(tmp->data, selectpath)) {
				selectd=tmp;
				break;
			}
			tmp=tmp->next;
		}
	}

	tmp=dirs;	// concatenate the 2 sorted lists
	if(tmp) {
		if(files) {
			LLIST *tmp1=ll->get_last_el(tmp);
			tmp1->next=files;
			tmp1->next->prev=tmp1;
		}
	}
	else tmp=files;

	if(!selectd) selectd=tmp;

	return selectd;
}

void printFileList(LLIST *el, char *path) {
	LLIST *in=el;
	el=ll->get_first_el(el);

	s32 i, j, k;
	u32 numel=0;
	u32 inoffset=0;
	char *p, ram[33];

// get the number of files and get the number of the selected file
	LLIST *pel=el;
	while(pel) {
		numel++;
		if(pel==in) inoffset=numel;
		pel=pel->next;
	}

// create and print the header
	u32 ilen=std->strlen(path);	// initial lenght
	std->sprintf(ram, " : %d files", numel);
	u32 flen=32-std->strlen(ram);	// final lenght
	if(ilen>flen) std->iprintf("%c%s", '~', path+ilen-flen+1);
	else std->iprintf("%s", path);
	std->iprintf("\x1b[0;%dH%s", flen, ram);

// get the first element to print
	if(numel>=23) {
		el=in;
		i=0;

		int depassement=inoffset+(23-11-1)-numel;
		if(depassement>0)
			while(el->prev && (int)i<11+depassement) {	// remonte de plus de 11 éléments de manière à avoir le dernier élément en dernière position sur l'écran
				el=el->prev;
				i++;
			}
		else
			while(el->prev && i<11 &&	// remonte de 11 éléments max
				depassement<=(int)i) {	// ne remonte pas jusqu'au dernier
				el=el->prev;
				i++;
			}
	}

// print the elements
	i=0;
	k=0;
	while(el && i<23) {	// print only 23 entries
		j=1;

		if(el==in) std->iprintf("\x1b[31m");	// red
			p=SF(el)->name;

			if(SF(el)->type) {	// a file
				if(std->strlen(p)>=32) {
					std->strncpy(ram, p, 32);
					ram[32]=0;
					p=ram;
					j=0;
				}
				std->iprintf("%s%s", k?"\n":"", p);	// print the return only if itsn't the first and if the previous was not using all the width
			}
			else {	// a directory
				if(std->strlen(p)>=30) {
					std->strncpy(ram, p, 30);
					ram[30]=0;
					p=ram;
					j=0;
				}
				std->iprintf("%s[%s]", k?"\n":"", p);
			}
		if(el==in) std->iprintf("\x1b[32;1m");	// green

		k=j;
		i++;
		el=el->next;
	}
}

int cmpSF(sFileT *a, sFileT *b) {
	if(a && b) return std->strcasecmp(a->name, b->name);
	else return 1;
}

